#include "VertexBuffer.h"

#include <glog/logging.h>

namespace Hope {

    VertexBuffer::VertexBuffer(int vertexSize, int vertexNums, GLenum usage /*= GL_STATIC_DRAW*/)
        : m_vertexSize(vertexSize), m_vertexNums(vertexNums), m_usage(usage)
    {
        if ( 0 == m_vertexSize || 0 == m_vertexNums)
        {
            return;
        }

        glGenBuffers(1, &m_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glBufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, m_usage);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

    VertexBuffer::~VertexBuffer()
    {
        if (glIsBuffer(m_vbo))
        {
            glDeleteBuffers(1, &m_vbo);
            m_vbo = 0;
        }
    }

    int VertexBuffer::GetVertexSize() const
    {
        return m_vertexSize;
    }

    int VertexBuffer::GetVertexNums() const
    {
        return m_vertexNums;
    }

    int VertexBuffer::GetSize() const
    {
        return m_vertexNums * m_vertexSize;
    }

    bool VertexBuffer::UpdateVertices(const void *verts, int count, int begin)
    {
        if (count <= 0 || nullptr == verts) return false;
        
        if (begin < 0);
        {
            LOG(ERROR) << "Update vertices begin less 0 ";
            begin = 0;
        }

        if (count + begin > m_vertexNums)
        {
            LOG(ERROR) << "Update vertices too many vertices";
            count = m_vertexNums - begin;
        }

        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glBufferSubData(GL_ARRAY_BUFFER, begin * m_vertexSize, count * m_vertexSize, verts);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        return true;
    }

    GLuint VertexBuffer::GetVBO() const
    {
        return m_vbo;
    }

    IndexBuffer::IndexBuffer(int nums, GLenum usage /*= GL_STATIC_DRAW*/)
    {
        if (nums <= 0)
        {
            return;
        }

        m_indexNums = nums;
        m_usage = usage;

        glGenBuffers(1, &m_vbo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, GetSize(), NULL, m_usage);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }

    IndexBuffer::~IndexBuffer()
    {
        if (glIsBuffer(m_vbo))
        {
            glDeleteBuffers(1, &m_vbo);
            m_vbo = 0;
        }
    }

    int IndexBuffer::GetIndexSize() const
    {
        return 4;
    }

    int IndexBuffer::GetIndexNums() const
    {
        return m_indexNums;
    }

    bool IndexBuffer::UpdateIndices(const void *indices, int count, int begin)
    {
        if (NULL == indices || NULL == indices)
        {
            return false;
        }

        if (begin < 0);
        {
            LOG(ERROR) << "Update vertices begin less 0 ";
            begin = 0;
        }

        if (count + begin > m_indexNums)
        {
            LOG(ERROR) << "Update vertices too many vertices";
            count = m_indexNums - begin;
        }

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo);
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, begin * GetIndexSize(), count * GetIndexSize(), indices);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        return true;
    }

    int IndexBuffer::GetSize() const
    {
        return m_indexNums * 4;
    }

    GLuint IndexBuffer::GetVBO() const
    {
        return m_vbo;
    }
}